package com.zy.controller;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.captcha.ShearCaptcha;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zy.common.DataGridView;
import com.zy.common.LoginToken;
import com.zy.common.ResultObject;
import com.zy.domain.Member;
import com.zy.domain.ReleaseTask;
import com.zy.domain.User;
import com.zy.param.LoginParam;
import com.zy.param.PayBindingParam;
import com.zy.param.RegisterParam;
import com.zy.service.MemberService;
import com.zy.service.UserService;
import com.zy.shiro.domain.SysUser;
import com.zy.shiro.service.SysUserService;
import com.zy.utils.HashMD5Util;
import com.zy.vo.SysUserVo;
import com.zy.vo.UserVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Api(value = "用户模块")
@RestController()
public class UserController {

  @Autowired
  private MemberService memberService;
  @Autowired
  private UserService userService;
  @Autowired
  private SysUserService sysUserService;

  @Autowired
  private StringRedisTemplate stringRedisTemplate;
  public static final  String VALIDATE_CODE_PREFIX="validate:";


  /**
   * 删除用户
   */
  @PostMapping("/sys/user/deleteUser")
  public ResultObject deleteUser(Integer id){
    try {
//      Long roleId = sysRole.getRoleId();
//      sysRoleService.removeById(id);
      SysUser sysUser = sysUserService.getById(id);
      sysUser.setStatus(0);
      sysUserService.updateById(sysUser);
      return new ResultObject(1,"删除用户成功！");
    }catch (Exception e){
      return new ResultObject(-1,"删除用户失败！");
    }
  }
  /**
   * 删除用户
   */
  @PostMapping("/sys/user/blockUser")
  public ResultObject blockUser(Integer id){
    try {
//      Long roleId = sysRole.getRoleId();
//      sysRoleService.removeById(id);
      SysUser sysUser = sysUserService.getById(id);
      sysUser.setStatus(0);
      sysUserService.updateById(sysUser);
      return new ResultObject(1,"拉黑用户成功！");
    }catch (Exception e){
      return new ResultObject(-1,"拉黑用户失败！");
    }
  }
  @PostMapping("/sys/user/updateuser")
  public ResultObject updateRole(SysUser sysUser){
    try {
//      sysRole.setCreateTime(new Date());
//      SysUser sysUser= (SysUser) SecurityUtils.getSubject();
//      sysRole.setCreateUserId((long) 1);
      String password = sysUser.getPassword();
      sysUser.setPassword(HashMD5Util.getMd5(password,2));
      sysUserService.updateById(sysUser);
//      sysRoleService.updateById(sysRole);
      return new ResultObject(1,"修改用户成功！");

    }catch (Exception e){
      return new ResultObject(-1,"修改用户失败！");
    }
  }

  @GetMapping("/sys/user/loadAllUser")
  public DataGridView loadAllRole(SysUserVo sysUserVo){
    if (sysUserVo==null){
      new DataGridView();
    }
    Page<SysUser> page =new Page<>(sysUserVo.getPage(),sysUserVo.getLimit());
//    page.setSize(roleVo.getLimit());
//    page.setPages(roleVo.getPage());
    IPage<SysUser> sysRoleIPage = sysUserService.queryAllUser(page, sysUserVo);
//    List<SysRole> list = sysRoleService.list();
    DataGridView dataGridView = new DataGridView(sysRoleIPage.getTotal(),sysRoleIPage.getRecords());
    return dataGridView;
  }

  @ApiOperation(value = "用户签到")
  @ApiImplicitParam(name = "uid",value = "用户id")
  @GetMapping("signIn")
  public String signIn(@RequestParam String uid) {
   User user= userService.signIn(uid);
   return user==null?"签到失败":"签到了"+user.getQiandao()+"次!";
  }

  //充值任务积分
  @ApiOperation("充值任务积分")
  @PostMapping("rechargeTaskMoney")
  public Object rechargeTaskMoney(@RequestParam String uid,String type,Double money){
// uid用户id

// 充值类型 0 支付宝 1 微信
// 充值金额
    User user = userService.rechargeTaskMoney(uid, type, money);
    return user==null?"充值失败！":user;
  }
  //提现任务积分
  @ApiOperation("提现任务积分")
  @PostMapping(value = "withdrawalTaskMoney",produces = "text/html;charset=utf-8")
  public Object withdrawalTaskMoney(@RequestParam String uid,String type,Double money){
// uid用户id

// 提现类型 0 支付宝 1 微信 2 银行卡
// 提现金额
    User user = userService.withdrawalTaskMoney(uid, type, money);
    return user==null?"提现失败！":user;
  }
  //提现指间积分
  @ApiOperation("提现指间积分")
  @PostMapping("withdrawalZhijianMoney")
  public Object withdrawalZhijianMoney(@RequestParam String uid,String type,Double money){
// uid用户id

// 提现类型 0 支付宝 1 微信 2 银行卡

// 提现金额
    User user = userService.withdrawalZhijianMoney(uid, type, money);
    return user==null?"提现失败！":user;
  }
  //充值会员
  @ApiOperation("充值成为会员")
  @PostMapping("/becomeMember")
  public Object becomeMember(@RequestParam String uid, @RequestParam Integer memberLevel,@RequestParam Integer memberType){

//    User user = userService.selectUserById(id);
//    boolean b = memberService.becomeMember(id, memberLevel, memberType);
//    if (b)
//    return releaseTaskService.getTaskById(id);
    Member member = memberService.becomeMember(uid, memberLevel, memberType);

    return member==null?"充值失败!":member;
  }
  @ApiOperation("支付绑定")
  @PostMapping("/payBinding")
  public Object payBinding(@RequestBody PayBindingParam payBindingParam){
    checkPayBindingParam(payBindingParam);
    User user = userService.payBinding(payBindingParam);
    return  user==null?"绑定失败！":user;
  }
  /**
   * 验证码的处理
   */
//  @SneakyThrows // 自动的关闭资源
  @ApiOperation("获取验证码")
  @GetMapping("/captcha")
  public ResponseEntity<Void> getCaptcha(String uuid, HttpServletResponse response){
    // 使用hutool 生成一个图片
    LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 50, 4, 3);
    String validateCode = lineCaptcha.getCode();
    stringRedisTemplate.opsForValue().set(VALIDATE_CODE_PREFIX+uuid,validateCode,1, TimeUnit.MINUTES);
    ServletOutputStream outputStream = null ;
    try {
      outputStream = response.getOutputStream();
      lineCaptcha.write(outputStream);
    } catch (IOException e) {
      e.printStackTrace();
    }
    return  ResponseEntity.ok().build();
  }

  @GetMapping("/sys/user/info")
  public ResponseEntity<SysUser> getCurrentUser(){
    // 从shiro 里面获取当前的登录对象
//    SysUser sysUser = (SysUser) SecurityUtils.getSubject().getPrincipal();
    SysUser sysUser = sysUserService.getById(1);
    return ResponseEntity.ok(sysUser) ;
  }

  @PostMapping("/login")
  @ApiOperation(value = "用户登录")
//  @ApiImplicitParams({
//    @ApiImplicitParam(name = "")
//  })
  @ResponseBody
  public LoginToken doLogin(@RequestBody LoginParam loginParam) {
//        checkLoginParam(loginParam);
//    checkValidateCode(loginParam);
    String username = loginParam.getUsername();
    String pwd = HashMD5Util.getMd5(loginParam.getPassword(), 2);
    SysUser sysUser = sysUserService.selectUser(username, pwd);
    if (loginParam.getUsername() == null || loginParam.getPassword() == null) {
//        throw new RuntimeException("请输入用户名和密码！");
      return new LoginToken(-1, "用户名或密码为空", null);
//      return ResponseEntity.ok("用户名或密码为空");
    }
    if (null == sysUser) {
//        throw new RuntimeException("用户不存在，请重新登录！");
      return new LoginToken(-1, "用户名或密码不正确", null);
//      throw new UnknownAccountException();// 没找到帐号
//      return ResponseEntity.ok("用户名或密码不正确！");
    }
    if (sysUser.getStatus()==0){
//      throw new LockedAccountException(); // 帐号锁定
//      return ResponseEntity.ok("用户已被禁用！");
      return new LoginToken(-1, "用户不可用", null);
    }
//    return new LoginToken(0, "登陆成功", user.getId());
//    return ResponseEntity.ok(sysUser.getUserId().toString());
      UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(loginParam.getUsername(), loginParam.getPassword());

      Subject subject = SecurityUtils.getSubject();

      subject.login(usernamePasswordToken); // 做登录
      // 登录成了，它把用户的登录信息写在sessions 里面，而sessions 里面key时SessionId
      String token = subject.getSession().getId().toString();
      // 只要有上面的key，我就是登录过来
//      return ResponseEntity.ok(token);
    return new LoginToken(0,"登陆成功",token);
//      return ResponseEntity.ok("登录成功！");


  }

  private void checkValidateCode(LoginParam loginParam) {
    String sessionUUID = loginParam.getSessionUUID();
    String imageCode = loginParam.getImageCode();
    if (StringUtils.hasText(sessionUUID)&&StringUtils.hasText(imageCode)){
      String redisCode = stringRedisTemplate.opsForValue().get(VALIDATE_CODE_PREFIX + sessionUUID);
      if(imageCode.equals(redisCode)){
        stringRedisTemplate.delete(VALIDATE_CODE_PREFIX+sessionUUID);
        return;
      }
    }
    throw  new AuthenticationException("验证码错误，请重新获取");
  }
//  private void checkLoginParam(LoginParam loginParam) {
//    String username = loginParam.getUsername();
//    String pwd = HashMD5Util.getMd5(loginParam.getPassword(),2);
//    User user = userService.selectUser(username,pwd);
//    System.out.println(user);
//    if (loginParam.getUsername() == null || loginParam.getPassword() == null) {
//      throw new RuntimeException("请输入用户名和密码！");
//    }
//    if (null == user) {
//      throw new RuntimeException("用户不存在，请重新登录！");
//    }
//  }

  @ApiOperation(value = "找回密码")
  @PostMapping("/getPwd")
  public ResponseEntity<String> getBackPassword(@RequestBody UserVo userVo) {

    checkUserVo(userVo);
    User userByPhone = userService.getUserByPhone(userVo.getPhoneNum());
    userByPhone.setPassword(userVo.getPassword());
    userByPhone.setUpdateDate(new Date());
    userService.updateById(userByPhone);
    return ResponseEntity.ok("密码已找回，请重新登录！");
  }

  private void checkUserVo(UserVo userVo) {
    String phoneNum = userVo.getPhoneNum();
    String firstInputPwd = userVo.getFirstInputPwd();
    String secondInputPwd = userVo.getSecondInputPwd();
    String verificationCode = userVo.getVerificationCode();
    if (phoneNum == null) {
      throw new RuntimeException("请先输入电话号码！");
    }
    if (firstInputPwd == null) {
      throw new RuntimeException("请输入新密码！");
    }
    if (secondInputPwd == null) {
      throw new RuntimeException("请输入新密码！");
    }
    if (verificationCode == null) {
      throw new RuntimeException("请输入发送您手机的验证码！");
    }
    if (!firstInputPwd.equals(secondInputPwd)) {
      throw new RuntimeException("您输入的密码不一致，请重新输入！");
    }
  }

  @ApiOperation(value = "用户注册")
  @PostMapping("/register")
  public User register(
    @RequestBody @Validated RegisterParam registerParam
  ) {
    checkRegisterParam(registerParam);
    User user = userService.selectUserByPhone(registerParam.getPhoneNum());
    if (user!=null){
      throw  new RuntimeException("用户已注册！");
    }
    User newUser = userService.registerUser(registerParam);
    if (newUser==null){
      return null;
    }
    else {
      System.out.println("注册用户为："+newUser);
      return newUser;
    }

  }

  @ApiOperation(value = "重置用户")
  @ApiImplicitParam(name = "phoneNum",value = "手机号",required = false,paramType = "form")
  @PostMapping("/reset")
  public User reset(
    @RequestParam String phoneNum
  ) {
    checkPhoneNum(phoneNum);
    User user1 = userService.selectUserByPhone(phoneNum);
    if (user1==null){
      throw  new RuntimeException("您手机绑定的用户不存在！");
    }
    User user2 = userService.resetUserByPhone(phoneNum);
    System.out.println("手机号为："+phoneNum+"的用户"+user1+"已重置，现在用户为"+user2);
    return user2;
  }

  private void checkPhoneNum(String phoneNum) {
    if (phoneNum==null){
      throw  new RuntimeException("您输入的手机号不能为空！");
    }
    if (phoneNum.length()!=11){
      throw  new RuntimeException("请输入11位数的手机号！");
    }


  }

  private void checkRegisterParam(RegisterParam registerParam) {
    //注册表单的昵称
    String nickname = registerParam.getNickName();
    //注册表单的手机号
    String phoneNum = registerParam.getPhoneNum();
    //注册表单的短信验证码
    String verificationCode = registerParam.getVerificationCode();
    //注册表单的密码
    String password = registerParam.getPassword();
    //注册表单的推荐人手机号
    String parentPhone = registerParam.getParentPhone();

//    if (nickname==null||phoneNum==null||verificationCode==null||password==null||parentPhone==null){
//      throw new RuntimeException("");
//    }
    if (nickname == null) {
      throw new RuntimeException("请输入昵称！");
    }
    if (phoneNum == null) {
      throw new RuntimeException("请输入手机号！");
    }
    if (verificationCode == null) {
      throw new RuntimeException("请输入发送您手机上的短信验证码！");
    }
    if (password == null) {
      throw new RuntimeException("请输入要注册的密码！");
    }
    if (parentPhone == null) {
      throw new RuntimeException("请输入推荐人手机号！");
    }
  }

  private void checkPayBindingParam(PayBindingParam payBindingParam) {
    //用户id
    String userId = payBindingParam.getUserId();
    //姓名
    String name = payBindingParam.getName();
    //开户银行
    String bankName = payBindingParam.getBankName();
    //开户支行
    String bankKaihu = payBindingParam.getBankKaihu();
    //银行卡号
    String bankNum = payBindingParam.getBankNum();
    //支付宝账号
    String aliName = payBindingParam.getAliName();
    if (name==null||bankName==null||bankKaihu==null||bankNum==null||aliName==null){
      throw new RuntimeException("参数不能为空！");
    }
    if (userId==null){
      throw  new RuntimeException("用户不能为空！");
    }
  }

}
